package com.fdb.efp.esb.service.impl.esb;

import com.fdb.efp.esb.common.client.resp.EsbRespServiceBean;
import com.fdb.efp.esb.common.client.resp.EsbRespSysHeadBean;
import com.fdb.basic.framework.core.exception.ESBException;
import com.fdb.basic.framework.core.util.SpringContextUtils;
import com.fdb.basic.sequence.service.DefaultPatternDescriptor;
import com.fdb.basic.sequence.service.PatternDescriptor;
import com.fdb.efp.esb.service.bo.req.ZXQueryReports;
import com.fdb.efp.esb.service.client.ESBClientFactory;
import com.fdb.efp.esb.service.client.impl.MSESBBeanCreator;
import com.fdb.efp.esb.service.facade.esb.EsbService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Base64;
import java.util.Optional;
import java.util.function.Function;

import static com.fdb.basic.sequence.service.DefaultPatternDescriptor.*;

/**
 * 通用ESB服务调用模板
 *
 * @author F嘉阳
 * @date 2020/3/11 14:11
 */
public abstract class BaseEsbService<Q extends ZXQueryReports, P> implements EsbService<Q,P> {

    private static Logger log = LoggerFactory.getLogger(BaseEsbService.class);

    private final Base64.Encoder encoder = Base64.getEncoder();

    private static final PatternDescriptor pattern =
            DefaultPatternDescriptor.of("ESB" + YEAR_2 + MONTH + DAY + HOUR + MIN + SECOND + SEQ, 10);

    /**
     * 对queryReports进行预处理（可选),由子类实现
     * @param reqBean
     */
    protected void preProcess(Q reqBean) {};

    /**
     * 对接口返回结果进行处理，并返回包装后的结果
     * @param reqBean
     * @param resBean
     * @return
     * @throws Exception
     */
    protected abstract P postProcess(Q reqBean, P resBean) throws Exception;

    /**
     * 各接口的交易码
     * @return
     */
    protected abstract String tradeNo();

    /**
     * 各接口的服务场景
     * @return
     */
    protected abstract String scene();

    /**
     * 各接口实现需提供将 返回JSON 转换为 Bean 的转换策略
     * @return
     */
    protected abstract Function<String , P> converter() ;

    /**
     * 服务处理
     *
     * @return
     * @throws Exception
     */
    @Override
    public final P service(Q reqBean) throws Exception{
        log.info("调用ESB服务开始， 请求参数：" + reqBean);

        preProcess(reqBean);

        try {
            EsbRespServiceBean esbRespServiceBean = ESBClientFactory.buildClient()
                    .withBody(reqBean)
                    .withTradeNo(tradeNo())
                    .withScene(scene())
                    .withESBBeanFactory((MSESBBeanCreator) SpringContextUtils.getBean("MSESBBeanCreator"))
                    .create()
                    .sendAndReceive();
            EsbRespSysHeadBean esbRespSysHeadBean = esbRespServiceBean.getSysHead();
            P resBean = esbRespServiceBean.getBody(converter());
            if (!StringUtils.equals(esbRespSysHeadBean.getRetInfArry().get(0).getRetCd(),"000000")) {
                StringBuilder errMsg = new StringBuilder("调用ESB服务异常");
                Optional.of(esbRespSysHeadBean).map(e -> e.getRetInfArry().get(0).getRetMsg())
                        .ifPresent(s -> errMsg.append(",错误信息: ").append(s));
                throw new ESBException(errMsg.toString());
            }
            return postProcess(reqBean, resBean);
        } catch (ESBException e) {
            log.error(e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new ESBException(e);
        }
    }

}
